package com.example.elasticsearch;

import com.example.elasticsearch.entity.Goods;
import com.example.elasticsearch.mapper.GoodsMapper;
import com.example.elasticsearch.mapper.GoodsRepository;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.SearchScrollHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;

/**
 * 必须添加类描述
 *
 * @author HTJT
 * @date 2023/3/7 15:11
 * @version 1.0
 */
@SpringBootTest
@RunWith(SpringRunner.class)
public class scroll {

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private GoodsRepository goodsRepository;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 滚动查询所有数据
     */
    @Test
    public void scrollQuery1() {
        // 设置每页数据量
        int pageSize = 10;
        MatchAllQueryBuilder queryBuilder = QueryBuilders.matchAllQuery();//条件
        FieldSortBuilder sortBuilder = new FieldSortBuilder("id").order(SortOrder.ASC);//排序
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(queryBuilder).withSort(sortBuilder).build();
        nativeSearchQuery.setMaxResults(pageSize);// 设置每页数据量

        long scrollTimeInMillis = 60 * 1000;//设置缓存内数据的保留时间，不要把缓存时时间设置太长，否则占用内存。
        // 缓存第一页符合搜索条件的数据
        SearchScrollHits<Goods> searchScrollHits = elasticsearchRestTemplate.searchScrollStart(scrollTimeInMillis, nativeSearchQuery, Goods.class, IndexCoordinates.of("goods"));
        String scrollId = searchScrollHits.getScrollId();

        int scrollTime = 1;
        while (searchScrollHits.hasSearchHits()) {// 判断searchScrollHits中是否有命中数据，如果为空，则表示已将符合查询条件的数据全部遍历完毕
            System.out.println("第" + scrollTime + "页数据，数据总数：" + searchScrollHits.getSearchHits().size());

            for (SearchHit<Goods> searchHit : searchScrollHits.getSearchHits()) {// 从缓存中读取数据
                Goods goods = searchHit.getContent();
                System.out.println(goods);
            }
            // 根据上次搜索结果scroll_id进入下一页数据搜索
            searchScrollHits = elasticsearchRestTemplate.searchScrollContinue(scrollId, scrollTimeInMillis, Goods.class, IndexCoordinates.of("goods"));//该方法执行后将重新刷新快照保留时间
            scrollId = searchScrollHits.getScrollId();
            scrollTime = scrollTime + 1;
        }

        List<String> scrollIds = new ArrayList<>();
        scrollIds.add(scrollId);
        elasticsearchRestTemplate.searchScrollClear(scrollIds);// 清除 scroll
    }


    /**
     * 根据查询条件滚动查询
     * 可以用来解决深度分页查询问题
     */
    @Test
    public void scrollQuery2() {

        // 假设用户想获取第70页数据，其中每页10条
        int pageNo = 70;
        int pageSize = 10;

        // 构建查询条件
        MatchAllQueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
        FieldSortBuilder sortBuilder = new FieldSortBuilder("id").order(SortOrder.ASC);//排序
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withSort(sortBuilder)
                .build();
        nativeSearchQuery.setMaxResults(pageSize);// 设置每页数据量

        long scrollTimeInMillis = 60 * 1000;//设置缓存内数据的保留时间
        //1、缓存第一页符合搜索条件的数据
        SearchScrollHits<Goods> searchScrollHits = elasticsearchRestTemplate.searchScrollStart(scrollTimeInMillis, nativeSearchQuery, Goods.class, IndexCoordinates.of("goods"));
        String scrollId = searchScrollHits.getScrollId();
        int scrollTime = 1;
        // 判断searchScrollHits中是否有命中数据，如果为空，则表示已将符合查询条件的数据全部遍历完毕
        while (searchScrollHits.hasSearchHits() && scrollTime < pageNo) {
            // 根据上次搜索结果scroll_id进入下一页数据搜索
            searchScrollHits = elasticsearchRestTemplate.searchScrollContinue(scrollId, scrollTimeInMillis, Goods.class, IndexCoordinates.of("goods"));//该方法执行后会重新刷新快照保留时间
            scrollId = searchScrollHits.getScrollId();
            scrollTime = scrollTime + 1;
        }

        List<String> scrollIds = new ArrayList<>();
        scrollIds.add(scrollId);

        // 清除 scroll
        elasticsearchRestTemplate.searchScrollClear(scrollIds);

        //4、 从缓存中读取数据
        for (SearchHit<Goods> searchHit : searchScrollHits.getSearchHits()) {
            Goods goods = searchHit.getContent();
            System.out.println(goods);
        }
    }






}
